import 'dart:io';

import 'package:dio/dio.dart';
import 'package:meta/meta.dart';

const int ERROR_CODE_UNKNOWN = -1;
const int ERROR_CODE_DIO = -2;
const int ERROR_CODE_ERROR = -3;

@immutable
class ApiException {
  final int code;
  final String msg;
  final String showMsg;

  ApiException({this.code, this.msg, this.showMsg});

  static ApiException parseDioError(DioError error) {
    int code = ERROR_CODE_DIO;
    String showMsg = "";
    switch (error.type) {
      case DioErrorType.CANCEL:
        showMsg = "请求已取消";
        break;
      case DioErrorType.CONNECT_TIMEOUT:
        showMsg = "请求连接超时";
        break;
      case DioErrorType.SEND_TIMEOUT:
        showMsg = "请求超时";
        break;
      case DioErrorType.RECEIVE_TIMEOUT:
        showMsg = "请求响应超时";
        break;
      case DioErrorType.DEFAULT:
        showMsg = error.message;
        if (error.error is SocketException) {
          code = (error.error as SocketException).osError.errorCode;
          if (code == 101 || code == 7) showMsg = "网络连接失败";
        }
        break;
      case DioErrorType.RESPONSE:
        try {
          code = error.response.statusCode;
          switch (code) {
            case 400:
              showMsg = "请求语法错误";
              break;
            case 401:
              showMsg = "请求权限错误";
              break;
            case 403:
              showMsg = "服务器拒绝执行";
              break;
            case 404:
              showMsg = "无法访问请求";
              break;
            case 405:
              showMsg = "请求方法被禁止";
              break;
            case 500:
              showMsg = "服务器内部出错";
              break;
            case 502:
              showMsg = "无效的请求";
              break;
            case 505:
              showMsg = "不支持的http请求协议";
              break;
            default:
              showMsg = error.response.statusMessage;
          }
        } on Exception catch (e) {
          print(e.toString());
          code = ERROR_CODE_UNKNOWN;
          showMsg = "未知错误";
        }
        break;
      default:
        code = ERROR_CODE_UNKNOWN;
        showMsg = "未知错误";
        break;
    }
    return ApiException(code: code, msg: error.message, showMsg: showMsg);
  }

  static ApiException parseExcetion(Exception e) => (e is DioError)
      ? parseDioError(e)
      : ApiException(
          code: ERROR_CODE_UNKNOWN, msg: e.toString(), showMsg: "未知错误");

  static ApiException parseError(Error e) => ApiException(
      code: ERROR_CODE_ERROR,
      msg: e.stackTrace.toString(),
      showMsg: e.toString());
}
